#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re, string, sys
productRe = "<li class='","&nbsp;&nbsp;&nbsp;</li>"
categoryRe = "<h2><strong>","</strong></h2>"
brandRe = "<strong>(?=[^<]*</strong><br />)","</strong><br />"
product = "<li class='","&nbsp;&nbsp;&nbsp;</li>"
category = "<h2><strong>","</strong></h2>"
brand = "<strong>","</strong><br />"
categorySeparator = "</strong><ul class='S'><strong>"
all1 = productRe + categoryRe + brandRe
allre = "(" + "|".join(all1) + ")"
sourceEncoding = "utf-8"
targetEncoding = "iso-8859-1"

class Index:
	
	def __init__(self, groupCount):
		self.index = {}
		self.groupCount = groupCount
		self.hasGroupIndex = self.groupCount>1	

	def addProducts(self, products):
		for product in products:
			keywords = product.keywords()
			for keyword in keywords:
				if not keyword in self.index:
					self.index[keyword] = []
				self.index[keyword].append(product.index)
				
	def get(self):
		self.listIndex = {}
		self.end2 = None
		ret = ""
		retSize = 0
		for keyword in sorted(self.index.keys()):
			if len(self.index[keyword])>1:
				self.listIndex[keyword] = retSize
				record = ",".join([ str(x) for x in self.index[keyword]]) + "\n"
				ret += record
				retSize += len(record)
		self.end2 = retSize
		return ret
	
	def getAlphabeticalIndex(self):
		self.groupIndex = {}
		self.end = None
		ret = ""
		count = 0
		
		for keyword in sorted(self.index.keys()):
			if count == 0 and self.hasGroupIndex:
				self.groupIndex[keyword] = len(ret)			
			value = keyword in self.listIndex and ("i" + str(self.listIndex[keyword])) or str(self.index[keyword][0])
			ret += keyword + "-" + str(value) + "-"
			count += 1
			if count==self.groupCount:
				count = 0
		
		if not self.hasGroupIndex:		
			ret+="end-0-end2-" + str(self.end2) + "\n"
		else:
			ret = ret[:len(ret)-1] + '\n'
			self.end = len(ret)
		return ret


	def getGroupIndex(self):
		ret=""
		if self.hasGroupIndex:
			for keyword in sorted(self.groupIndex.keys()):
				value = str(self.groupIndex[keyword])
				ret += keyword + "-" + str(value) + "-"
			ret += "end-" + str(self.end) + "-end2-" + str(self.end + self.end2) + "\n"
		return ret

class Product:
	def __init__(self):
		self.name = None
		self.spiga = False
		self.ministero = False
		self.grossista = False
		self.category = None
		self.brand = None
		self.index = None
		
	def get(self):
		a = self.spiga and "1" or "0"
		b = self.ministero and "1" or "0"
		c = self.grossista and "1" or "0"		
		return "3" + a + b + c + self.name + u"§" + (not self.category is None and str(self.category.index) or "None") + u"§" + (not self.brand is None and str(self.brand.index) or "None") + "\n"	
	
	def keywords(self):
		kwds = getKeywords(self.name)
		kwds = kwds.union(self.category.keywords())
		kwds = kwds.union(self.brand.keywords())
		return kwds
		
	def __repr__(self):
		return "Product(" + str(self.spiga) + "," + str(self.ministero) + "," + str(self.grossista) + "," + self.name + ")"

class Brand:
	def __init__(self):
		 self.name = None
		 self.index = None
		 self.__keywords = None

	def get(self):
		return "2" + self.name + "\n"

	def keywords(self):
		if self.__keywords is None:
			self.__keywords = getKeywords(self.name)
		return self.__keywords

	def __repr__(self):
		return "Brand(" + self.name + ")"

class Category:
	def __init__(self):
		self.name = None
		self.englishName = None
		self.index = None
		self.__keywords = None
		
	def get(self):
		return "1" + self.name + "," + self.englishName + "\n"

	def keywords(self):
		if self.__keywords is None:
			self.__keywords = getKeywords(self.name).union(getKeywords(self.englishName))
		return self.__keywords
		
	def __repr__(self):
		return "Category(" + self.name + "," + self.englishName + ")"

def getKeywords(name):
	keywords = name.split()
	ret = []
	for keyword in keywords:
		for keyword1 in re.split("[" + string.punctuation + u"’“”" + "]", keyword):
			if len(keyword1) > 2:
				ret.append(keyword1.lower())
	return set(ret)

def stripTags(value):
    "Return the given HTML with all tags stripped."
    return re.sub(r'<[^>]*?>', '', value) 

def readCategory(category):
	cat = Category()
	category = category.split(categorySeparator)	
	cat.name = re.sub("\ \ +", " ", category[0])
	cat.englishName = re.sub("\ \ +", " ", category[1])
	return cat

def readProduct(product):
	p = Product()
	p1 = product.split("'>")
	if p1[0].find("s")>=0:
		p.spiga = True
	if p1[0].find("m")>=0:
		p.ministero = True
	if p1[0].find("g")>=0:
		p.grossista = True

	
	p.name = stripTags(p1[1]).strip()
	p.name = re.sub("\ \ +", " ", p.name)
	return p

def readBrand(brand):
	b = Brand()
	b.name = stripTags(brand).strip()
	b.name = re.sub("\ \ +", " ", b.name)
	return b

def prepareCategories(categories):
	i = 0
	for category in categories:
		category.index = i
		r = category.get()
		i+= len(r)
	return i

def prepareBrands(brands, i):
	j = 0
	for brand in brands:
		brand.index = i + j
		r = brand.get()
		j += len(r)
	return i+j
		
def prepareProducts(products, j):
    k = 0
    for product in products:
        product.index = j + k
        r = product.get()
        k += len(r)
    return k
groupCount=10
if len(sys.argv)<1:
	sys.exit(1)
if len(sys.argv)>=3:
	groupCount = int(sys.argv[2])
try:
	groupCount = int(sys.argv[1])
	f = sys.stdin
except:	
	if len(sys.argv)==1:
		f = sys.stdin
	else:
		location = sys.argv[1]
		f = open(location)
handbook = f.read().decode(sourceEncoding)
handbook = handbook.replace(u"–",u"-")
handbook = handbook.replace(u"’","'")
handbook = handbook.replace(u"“","\"")
handbook = handbook.replace(u"”","\"")
handbook = handbook.replace(u"…","...")
handbook = handbook.replace(u"…","...")
handbook = handbook.replace(u'\u0148','n')

splitted = re.split(allre,handbook)
categories = []
brands = []
products = []

lastCategory = None
lastBrand = None
brandsMap = {}
for i in range(len(splitted)):
	piece = splitted[i]
	if piece == product[0]:
		p = readProduct(splitted[i+1].strip())
		p.category = lastCategory
		p.brand = lastBrand
		products.append(p)
	elif piece == category[0]:
		lastCategory = readCategory(splitted[i+1].strip())
		categories.append(lastCategory)
	elif piece == brand[0]:
		if not lastBrand is None:
			brandsMap[lastBrand.name] = lastBrand
		lastBrand = readBrand(splitted[i+1].strip())
		if lastBrand.name in brandsMap:
			lastBrand = brandsMap[lastBrand.name]
		else:
			brands.append(lastBrand)
		
i = prepareCategories(categories)
j = prepareBrands(brands, i)
k = prepareProducts(products, j)

index = Index(groupCount)
index.addProducts(products)

indexEncoded = index.get().encode(targetEncoding)
alphabeticalIndexEncoded = index.getAlphabeticalIndex().encode(targetEncoding)
groupIndex = index.getGroupIndex().encode(targetEncoding)
if index.hasGroupIndex:
	print 1
	print groupIndex,
else:
	print 0
print alphabeticalIndexEncoded,
print indexEncoded,
for category in categories:
	print category.get().encode(targetEncoding),
for brand in brands:
	print brand.get().encode(targetEncoding),
for product in products:
	print product.get().encode(targetEncoding),
